#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <pthread.h>
#include <semaphore.h>
#include <wait.h>
#include <signal.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <sys/socket.h>
#include <sys/ipc.h>
#include <sys/sem.h>
#include <semaphore.h>
#include <sys/msg.h>
#include <sys/shm.h>
#include <sys/un.h>
#include <sys/epoll.h>
#include <iostream>
#include <map>
#include <list>
#include <vector>
#include <dirent.h>

#include "pack.h"
#include "dbhelper.h"


using namespace std;


void sendOnlineListToClient(int target_client);

bool client_handler(int client,dbHelper& db);


struct User{
	string username;
	FILE* fp;
	string videoTarget; // 视频目标用户
	// 处理分包时需要以下3个数据
	Pack readed_pack; // 用来暂存已经读取到的部分协议包 以及 用来拼接未读取的协议包
	int readed_pack_size = 0; // 用来记录已读协议包的大小
	int unreaded_pack_size = 0; // 用来记录未读协议包的大小

	 // 处理4个字节的size 发生分包的可能性
	int readed_size = 0;
	int readed_size_size = 0;
	int unreaded_size_size = 0;
};

template <class T1,class T2>
class mymap:public map<T1,T2>{
public:
    // 重命名查找函数，避免与operator[]冲突
    int findByUsername(const string& name){
        for(const auto& ele:*this){
            if(ele.second.username == name){
                return ele.first;
            }
        }
        return -1;
    }

    T2& operator[](const T1& key){
        return this->map<T1,T2>::operator[](key);
    }
};
pthread_mutex_t map_mutex = PTHREAD_MUTEX_INITIALIZER;
mymap<int,User> m;// 键为：客户端套接字，值为 User 对象
// 这个map的作用为：存储所有在线用户的套接字信息和用户的相关信息

// 全局变量
int mcu_server;  // 单片机专用服务器socket
int mcu_count=0;

// 在main函数中创建单片机专用端口
int create_mcu_server(short port) {
    int server = socket(AF_INET, SOCK_STREAM, 0);
    struct sockaddr_in addr = {0};
    addr.sin_family = AF_INET;    
    addr.sin_port = htons(port);
    addr.sin_addr.s_addr = inet_addr("0.0.0.0");
    
    if(bind(server,(struct sockaddr*)&addr,sizeof(addr)) == -1){
        perror("bind mcu server");
        return -1;
    }
    
    listen(server, 10);
    return server;
}


int main(int argc, const char *argv[])
{
	signal(SIGPIPE, SIG_IGN);
	if(argc < 2){
		printf("请末端口号\n");
		return 1;
	}

	dbHelper db("user.db");

	short port = atoi(argv[1]);
	// "abc123" -> 0
	int server = socket(AF_INET,SOCK_STREAM,0);
	
    // 创建单片机专用服务器（端口号+1）
    mcu_server = create_mcu_server(port + 1);
    if(mcu_server == -1) {
        printf("创建单片机服务器失败\n");
    } else {
        printf("单片机服务器监听端口: %d\n", port + 1);
    }
    
	struct sockaddr_in addr = {0};
	addr.sin_family = AF_INET;	
	addr.sin_port = htons(port);
	addr.sin_addr.s_addr = inet_addr("0.0.0.0");

	if(bind(server,(struct sockaddr*)&addr,sizeof(addr)) == -1){
		perror("bind");
		return 1;
	}

	listen(server,10);

	// 创建epoll监视列表
	int epfd = epoll_create1(EPOLL_CLOEXEC);

	// 将 0 和 server 添加进入监视列表
	//struct epoll_event epoll_stdin = {.events = EPOLLIN ,data:{fd:server}};
	struct epoll_event epoll_stdin = {events : EPOLLIN , data:{fd:0}};
	struct epoll_event epoll_server = {events : EPOLLIN , data:{fd : server}};

	epoll_ctl(epfd,EPOLL_CTL_ADD,0,&epoll_stdin);
	epoll_ctl(epfd,EPOLL_CTL_ADD,server,&epoll_server);
	    if(mcu_server != -1) {
        struct epoll_event epoll_mcu_server = {events : EPOLLIN , data:{fd : mcu_server}};
        epoll_ctl(epfd,EPOLL_CTL_ADD,mcu_server,&epoll_mcu_server);
    }



	while(1){
		// 提前准备一个激活列表
		struct epoll_event list[20] = {0};
		int count = epoll_wait(epfd,list,20,-1);

		for(int i=0;i<count;i++){
			// list里面全都是激活的描述符，最多判断一下 ，以何种方式激活的

			// 将激活的具体描述符单独取出
			int fd = list[i].data.fd;
			if(fd == 0){
				char buf[1024] = "";
				scanf("%s",buf);
				getchar();
				printf("键盘输入数据:%s\n",buf);
				continue;
			}

            if(fd == server || fd == mcu_server){
                printf("有客户端连接\n");
                struct sockaddr_in client_addr = {0};
                socklen_t client_len = sizeof(client_addr);
                int client = accept(fd,(struct sockaddr*)&client_addr,&client_len);
                printf("新连接的客户端的ip = %s\n",inet_ntoa(client_addr.sin_addr));
                printf("新连接的客户端的port = %d\n",ntohs(client_addr.sin_port));
                
                pthread_mutex_lock(&map_mutex);
                
                if(fd == mcu_server) {
                	
                    // 单片机专用端口的连接，自动标记为单片机
                    mcu_count++;
                    m[client].username = "MCU_" + std::to_string(client);
                    printf("单片机客户端 %d 通过专用端口连接\n", client);
                } else {
                    // 主端口的连接，等待登录
                    printf("普通客户端，等待登录\n");
                }
                
                pthread_mutex_unlock(&map_mutex);
                
                struct epoll_event epoll_client = {events : EPOLLIN , data:{fd : client}};
                epoll_ctl(epfd,EPOLL_CTL_ADD,client,&epoll_client);
                continue;
            }

			// 剩下的都是客户端描述符
            bool res = client_handler(fd,db);
            if(res == false){
                epoll_ctl(epfd,EPOLL_CTL_DEL,fd,nullptr);
                pthread_mutex_lock(&map_mutex);
                m.erase(fd);
                if (m[fd].username.find("MCU_") == 0){
                	mcu_count--;
                }
                pthread_mutex_unlock(&map_mutex);
            }
		}
		
	}
	return 0;
}

bool client_handler(int client, dbHelper& db) {
    // 首先检查客户端是否仍然连接
    int error = 0;
    socklen_t len = sizeof(error);
    if(getsockopt(client, SOL_SOCKET, SO_ERROR, &error, &len) != 0 || error != 0) {
        cout << "客户端 " << client << " 已断开连接" << endl;
        return false;
    }
    while (1) {
        int size = 0;
        int res = 0;
        Pack pack;

if (m[client].username.find("MCU_") == 0) {
        char buf[4096] = {0};
        int res = recv(client, buf, sizeof(buf) - 1, MSG_DONTWAIT);
        
        if (res > 0) {
            // 成功接收单片机发送的字符串
            string mcu_message(buf, res);
            cout << "收到单片机消息: " << mcu_message << endl;
            
            size_t pos=0;
            
            while((pos = mcu_message.find('\n')) !=string::npos)
            {
            	string s_message=mcu_message.substr(0,pos);
            	mcu_message.erase(0, pos+1);
            	if(s_message.empty()) continue;
            	Pack s_pack;
		        if(s_message.find("TEM")!=string::npos)
		        	s_pack.setType(TYPE_TEM_HUM);
		        else if((s_message.find("bpm")!=string::npos) || (s_message.find("samples")!=string::npos))
		        	s_pack.setType(TYPE_HEART);
		        else if(s_message.find("detected")!=string::npos)
		        	s_pack.setType(TYPE_DETECTED);
		        else if(s_message.find("away")!=string::npos)
		        	s_pack.setType(TYPE_AWAY);
		        else if(s_message.find("lux")!=string::npos)
		        	s_pack.setType(TYPE_LUX);
		        else
		        	s_pack.setType(TYPE_ERROR);
		        s_pack<<s_message;
				// 替换原来的for循环
				pthread_mutex_lock(&map_mutex);  // 加锁保护整个遍历过程
				for(auto it = m.begin(); it != m.end(); ){
					if(it->second.username.find("MCU_") != 0){
						int error = 0;
						socklen_t len = sizeof(error);
						
						if(getsockopt(it->first, SOL_SOCKET, SO_ERROR, &error, &len) == 0 && error == 0) {
							// 发送数据
							ssize_t sent = send(it->first, (char*)&s_pack, s_pack.size(), MSG_DONTWAIT | MSG_NOSIGNAL);
							if(sent == -1) {
								cout<<"客户端 "<<it->first<<" 发送失败，可能已断开连接"<<endl;
								close(it->first);
								it = m.erase(it);  // 正确删除并移动迭代器
							} else {
								cout<<"成功转发数据给客户端 "<<it->first<<"，发送字节数: "<<sent<<endl;
								++it;  // 移动到下一个元素
							}
						} else {
							cout<<"客户端 "<<it->first<<" 套接字无效，进行清理"<<endl;
							close(it->first);
							it = m.erase(it);  // 正确删除并移动迭代器
						}
					} else {
						++it;  // 移动到下一个元素
					}
				}
				pthread_mutex_unlock(&map_mutex);  // 解锁
		        
			}
            return true;
        }
    }

        if (m[client].unreaded_pack_size != 0) {
            res = recv(client, (char*)&m[client].readed_pack + m[client].readed_pack_size, 
                      m[client].unreaded_pack_size, MSG_DONTWAIT);
            if (res != m[client].unreaded_pack_size) {
                m[client].readed_pack_size += res;
                m[client].unreaded_pack_size -= res;
                break;
            }
            pack = m[client].readed_pack;
            m[client].unreaded_pack_size = 0;
        } else {
            if (m[client].unreaded_size_size != 0) {
                recv(client, (char*)&m[client].readed_size + m[client].readed_size_size, 
                      m[client].unreaded_size_size, MSG_DONTWAIT);
                size = m[client].readed_size;
                m[client].unreaded_size_size = 0;
            } else {
                // 读取4字节size
                res = recv(client, (char*)&size, 4, MSG_DONTWAIT);
                if (res == -1) {
                    return true;
                } else if (res == 0) {
                    cout << "4字节recv结束" << endl;
                    return false;
                }
                // 处理size分包
                if (res != 4) {
                    // 修正点：原memcpy参数错误，应拷贝res字节（而非readed_size_size）
                    memcpy(&m[client].readed_size, &size, res);  
                    m[client].readed_size_size = res;
                    m[client].unreaded_size_size = 4 - res;
                    break;
                }
            }

            // 读取size-4字节的包内容
            res = recv(client, (char*)&pack + 4, size - 4, MSG_DONTWAIT);
            if (res == 0) {
                cout << "size-4字节recv结束" << endl;
                return false;
            } else if (res == -1) {
                return true;
            }
            pack.setSize(size);

            // 处理包内容分包
            if (res != size - 4) {
                cout << "发生分包" << endl;
                memcpy(&m[client].readed_pack, &pack, res + 4);
                m[client].readed_pack_size = res + 4;
                m[client].unreaded_pack_size = size - m[client].readed_pack_size;
                break;
            }
        }

        switch (pack.getType()) {
            case TYPE_REGIST: {
                vector<string> list = pack.readAll();
                string name = list[0];
                string pswd = list[1];
                bool res = db.regist(name, pswd);
                pack.setBack(res ? BACK_SUCCESS : BACK_ERR);
                pack >> client;
                break;
            }
            case TYPE_LOGIN: {
                vector<string> list = pack.readAll();
                string name = list[0];
                string pswd = list[1];
                bool res = db.login(name, pswd);
                if (res) {
                    pack.setBack(BACK_SUCCESS);
                    m[client].username = name;
                } else {
                    pack.setBack(BACK_ERR);
                }
                pack >> client;
                break;
            }
            case TYPE_ORDER: {
            	if(mcu_count==0)
            	{
            		cout<<"当前无被控端连接"<<endl;
            		pack.setType(TYPE_NOMCU);
            		pack>>client;
            		break;
            	}
                vector<string> list = pack.readAll();
                cout << "收到客户端发来的命令：" << list[0] << endl;
                string command = list[0];
                cout << "当前在线客户端数量：" << m.size() << endl;
                // 发送给所有MCU客户端
                for (auto& ele : m) {
                    if (ele.second.username.find("MCU_") == 0) {
                        ssize_t sent = send(ele.first, command.c_str(), command.length(), 0);
                        cout << "已发送指令给单片机 " << ele.first << ": " << command 
                             << " (长度:" << command.length() << ", 实际发送:" << sent << ")" << endl;
                    }
                }
                break;
            }
            // 建议添加default，处理未知类型的包
            default: {
                cout << "未知的包类型：" << pack.getType() << endl;
                break;
            }
        }  // 修正点：补全switch的闭合大括号
    }  // 修正点：补全while(1)的闭合大括号

    // 3. 修复返回值缺失：while循环意外退出时的默认返回值
    return false;
}  // 修正点：补全client_handler函数的闭合大括号
